#include "String.h"

namespace wxd
{
    const size_t string::npos = -1;
    const char *string::c_str() const
    {
        return _str;
    }

    size_t string::size() const
    {
        return _size;
    }

    size_t string::capacity() const
    {
        return _capacity;
    }

    void string::reserve(size_t n)
    {
        // std::cout<<"n:"<<n<<std::endl;
        if (n >= _size)
        {
            if (n > _capacity)
            {
                // 扩容
                char *tmp = new char[n + 1];
                // 拷贝
                strcpy(tmp, _str);
                // 销毁
                delete[] _str;
                // 赋值
                _str = tmp;
                // 修改
                _capacity = n;

                std::cout << "reserve success!" << std::endl;
            }
            else
            {
                // 缩容
                _capacity = n;
            }
        }
        // std::cout<<"dont need reserve"<<std::endl;
    }
    void string::push_back(char ch)
    {
        // 检测容量是否需要扩容/初始化
        if (_size == _capacity)
        {
            // 重置容量
            size_t new_capacity = _size == 0 ? 4 : 2 * _capacity;
            reserve(new_capacity);
        }

        _str[_size++] = ch;
    }

    void string::append(const char *str)
    {
        // 对指针进行判空
        assert(str != nullptr);
        size_t len = strlen(str);
        if (_size + len > _capacity)
        {
            // 扩容
            size_t new_capacity = _size + len > 2 * _capacity ? _size + len : 2 * _capacity;
            reserve(new_capacity);
        }
        // 插入
        strcpy(_str + _size, str);
        // 调整
        _size += len;
    }

    void string::erase(size_t pos, size_t len)
    {
        // 限制下标&&不能删除空string
        assert(_size > 0 && (pos >= 0 && pos < _capacity));
        // 重置长度
        len = len > (_capacity - pos) ? (_capacity - pos) : len;
        std::cout << len << std::endl;
        // 删除
        strcpy(_str + pos, _str + pos + len);
        _size -= len;
    }

    // insert
    void string::insert(size_t pos, char ch)
    {
        // 断言一下坐标
        assert(pos >= 0 && pos <= _capacity);
        // 扩容
        if (_size == _capacity)
        {
            size_t new_capacity = _size == 0 ? 4 : 2 * _capacity;
            reserve(new_capacity);
        }

        // 移动
        for (int end = _size; end >= (int)pos; end--) // 注意size_t 与 int 类型比较，int会转变为size_t，导致负数被解释为非常大的数字
        {
            _str[end + 1] = _str[end];
            // std::cout<<"end = "<<end<<std::endl;
        }
        std::cout << "pos = " << pos << std::endl;
        _str[pos] = ch;
        ++_size;
    }
    void string::insert(size_t pos, const char *str)
    {
        // 判坐标&&空指针
        assert(str != nullptr && (pos >= 0 && pos <= _capacity));
        // 计算长度
        size_t len = strlen(str);
        // 扩容
        if (_capacity - pos < len)
        {
            size_t new_capacity = pos + len > 2 * _capacity ? pos + len : 2 * _capacity;
            reserve(new_capacity);
        }
        // 移动
        for (int end = _size; end >= (int)pos; end--)
        {
            _str[end + len] = _str[end]; // 空出几个格子就加几
        }
        // 中间插入就不要用strcpy了
        // memcpy(_str+pos,str,strlen(str));
        _size += len;
    }
    size_t string::find(char ch, size_t pos) const
    {
        // 断言坐标
        assert(pos >= 0 && pos < _size);
        for (size_t i = pos; i < _size; i++)
        {
            if (_str[i] == ch)
                return i;
        }
        return npos;
    }
    size_t string::find(const char *str, size_t pos) const
    {
        assert(str != nullptr && (pos >= 0 && pos < _size));
        const char *ptr = strstr(_str + pos, str);
        if (ptr != nullptr)
        {
            return ptr - _str;
        }
        return npos;
    }

    string string::substr(size_t pos, size_t len) const
    {
        // 断言坐标
        assert(pos >= 0 && pos < _size);
        // 重置len
        len = len > _size - pos ? _size - pos : len;
        std::cout << len << std::endl;
        string tmp;
        int end = pos + len;
        for (; pos < end; pos++)
        {
            std::cout << pos << std::endl;

            tmp += _str[pos];
        }

        return tmp;
    }

    void string::clear()
    {
        _str[0] = '\0';
        _size = 0;
    }

    // 流插入
    std::ostream &operator<<(std::ostream &out, const string &s)
    {
        for (auto ch : s)
        {
            std::cout << ch;
        }
        // out << s.c_str();
        return out;
    }

    // 流提取
    std::istream &operator>>(std::istream &in, string &s)
    {
        s.clear();

        // char ch;
        // // in >> ch;
        // ch = in.get();
        // while (ch != ' ' && ch != '\n')
        // {
        //     s += ch;
        //     ch = in.get();
        // }
        char buff[DEFAULT_BUFFER_SIXE] = {0};
        char ch = in.get();
        size_t i = 0;
        while (ch != ' ' && ch != '\n')
        {
            buff[i++] = ch;
            ch = in.get();

            if (i == DEFAULT_BUFFER_SIXE - 1)
            {
                buff[i] = 0;
                s += buff;
                i = 0;
            }
        }
        // 把缓冲区剩余的内容存进去
        buff[i] = 0;
        s += buff;

        return in;
    }

    void getline(std::istream &in, string &s)
    {
        s.clear();
        char buff[DEFAULT_BUFFER_SIXE] = {0};
        char ch = in.get();
        size_t i = 0;
        while (ch != '\n')
        {
            buff[i++] = ch;
            ch = in.get();

            if (i == DEFAULT_BUFFER_SIXE - 1)
            {
                buff[i] = 0;
                s += buff;
                i = 0;
            }
        }
        // 把缓冲区剩余的内容存进去
        buff[i] = 0;
        s += buff;
    }
};
